#include <vector>
#include <iostream>
#include <sstream>
#include <string>
#include <math.h>
#include <sstream>
#include <iomanip>

#include "line.h"
#include "ReadFile.h"
#include "common.h"

using namespace std;

vector<float> vPower;
vector<string> vName;
vector<int> vCount;
float minValue;
float maxValue;
unsigned int scale;
bool bScale;
int pDistance;

Line::Line(const wxString& title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(880, 380))
{
    this->Connect(wxEVT_PAINT, wxPaintEventHandler(Line::OnPaint));
    this->Centre();
}


void Line::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);
    wxBrush brush(wxColour(255, 255, 255), wxTRANSPARENT);
    dc.SetBrush(brush);

    convert_from_IPC();
    read_power_profile();
    paint_power_profile(&dc);
    paint_legend(&dc);
}

void read_power_profile()
{
    ReadFlie(&vPower);
    ReadFlieProgram(&vName, &vCount);

    //PrintTraverse(&vPower);

    //Retrieve the min and max power values from the vector vPower
    MinMaxValue(&minValue, &maxValue, &vPower);

    //If the difference of min and max power is greater than 255,
    //there should be some mistake.

    bScale = (vPower.size() > NRESOLUTION)? true:false;
    scale = bScale?(static_cast<int> (ceil(vPower.size() / NRESOLUTION)))
                  :(static_cast<int> (NRESOLUTION / vPower.size()));

    //Calculate for each WATT, how many color value needs to be changed
    //For example, the range of the power is from 10 to 30 watt.
    //The range for color is from (0,90,90) to (255,90,90)
    //Then, for each watt, we increase 12 = (255 - 0)/(30-10).

    pDistance = static_cast<int> (NCOLOR / (maxValue - minValue));
}


void paint_power_profile(wxPaintDC* dc)
{
    //If the collected power values is larger than the pixes in the figure
    //Scale up
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned int rColor = 0;
    wxColour cTemp;
    if(bScale)
    {
        while(i < vPower.size())
        {
            rColor = static_cast<int>((vPower.at(i) - minValue)*pDistance);
            string sTemp;
            stringstream ss;
            ss << hex << rColor;
            ss >> sTemp;
            if(sTemp.length()==1)
                sTemp="0"+sTemp;
            sTemp = "#"+sTemp+"7070";
            wxString mystring (sTemp.c_str(), wxConvUTF8);
            cTemp.Set(mystring);
            dc->SetPen(wxPen(cTemp, 1, wxSOLID));
            dc->DrawRectangle(BASECORX+j, 45, 1, 80);
            wxRegion region1(BASECORX+j, 45, 1, 80);
            wxRect rect1 = region1.GetBox();
            dc->SetBrush(wxBrush(cTemp));
            dc->DrawRectangle(rect1);

            i+=scale;
            j++;
        }
        //draw the program names
        i = 0;
        while(i < vName.size()){
            unsigned sum = 0;
            for (j = 0; j <= i; j++){
                if (i == j)
                    sum += vCount.at(j) / 3;
                else
                    sum += vCount.at(j);
            }
            wxString wxTemp(vName.at(i).c_str(), wxConvUTF8);
            dc->DrawText(wxTemp, BASECORX + (sum) / scale, 135);
            i++;
        }
    }

    //If the collected power values is less than the pixes in the figure
    //Scale down

    else
    {
        /*First, set the boundaries for each data points.
         *vector boundary stores the START and END X coordinate
         *for each power data point.*/

        vector<int> sBoundaryX;
        vector<int>::iterator itPower;
        i = 0;
        while(i < vPower.size())
        {
            //For example, scale is 42,and the BASECORX is 0,
            //the X coordinates are (0+1+0*42, 0+1*42),
            //(0+1+1*42, 0+2*42), (0+1+2*42, 0+3*42) ...

            sBoundaryX.push_back(1+BASECORX+i*scale);
            //cout << "The pushed coordinateSTART is " << 1+BASECORX+i*scale << endl;
            //Define the color value for each power data
            //We only change the red color
            rColor = static_cast<int>((vPower.at(i) - minValue)*pDistance);
            //cout << "The rColor is " << rColor << endl;
            //All the mess to generate a wxstring representing colors
            string sTemp;
            stringstream ss;
            ss << hex << rColor;
            ss >> sTemp;
            if(sTemp.length()==1)
                sTemp="0"+sTemp;
            sTemp = "#"+sTemp+"7070";
            wxString mystring (sTemp.c_str(), wxConvUTF8);
            cTemp.Set(mystring);
            dc->SetPen(wxPen(cTemp, 1, wxSOLID));
            dc->DrawRectangle(sBoundaryX.at(i), 45, scale, 80);
            wxRegion region1(sBoundaryX.at(i), 45, scale, 80);
            wxRect rect1 = region1.GetBox();
            dc->SetBrush(wxBrush(cTemp));
            dc->DrawRectangle(rect1);
            i++;
        }

        //draw the program names
        i = 0;
        while(i < vName.size()){
            unsigned sum = 0;
            for (j = 0; j <= i; j++){
                if (i == j)
                    sum += vCount.at(j) / 3;
                else
                    sum += vCount.at(j);
            }
            wxString wxTemp(vName.at(i).c_str(), wxConvUTF8);
            dc->DrawText(wxTemp, BASECORX + (sum) * scale, 135);
            i++;
        }

    }
    //cout << "The Bscale is " << bScale <<endl;
    //cout << "The scale is " << scale <<endl;
    //cout << "The max is" << max << "; The min is " << min <<endl;
}

/*now, paint the legend figure (#007070) to (#ff7070)*/

void paint_legend(wxPaintDC* dc)
{
    for (unsigned int rColor = 0;rColor<256;rColor++)
    {
        string sTemp;
        stringstream ss;
        ss << hex << rColor;
        ss >> sTemp;
        if(sTemp.length()==1)
            sTemp="0"+sTemp;
        sTemp = "#"+sTemp+"7070";
        wxString mystring (sTemp.c_str(), wxConvUTF8);
        wxColour cTemp;
        cTemp.Set(mystring);
        dc->SetPen(wxPen(cTemp, 1, wxSOLID));
        dc->DrawRectangle(rColor+BASECORX, 205, 1, 80);
        wxRegion region1(rColor+BASECORX, 205, 1, 80);
        wxRect rect1 = region1.GetBox();
        dc->SetBrush(wxBrush(cTemp));
        dc->DrawRectangle(rect1);
    }
    //draw the legend text
    ostringstream sBuf;
    sBuf << fixed << setprecision(1) << minValue;
    string sM = "Min " + sBuf.str() + "W";
    wxString wxTemp1(sM.c_str(), wxConvUTF8);
    dc->DrawText(wxTemp1, BASECORX, 295);
    sBuf.str("");
    sBuf << maxValue;
    sM = "Max " + sBuf.str() + "W";
    wxString wxTemp2(sM.c_str(), wxConvUTF8);
    dc->DrawText(wxTemp2, BASECORX+NCOLOR-30, 295);
}



